package parserjc.jaccie;

import java.util.*;
import java.io.*;

/**
* Diese Klasse stellt die rekursive Struktur eines Baumes dar.
* Die Knoten (jeweils eine Instanz der Klasse) sind doppelt verkettet, d.h.
* jeder Knoten kennt seinen Vaterknoten (die Wurzel null) und die S�hne
* (bei den Bl�ttern null). Zudem kennt jeder Knoten sein Symbol und seine
* Attribute.
*/
public class EvaluatorTree implements Serializable, Cloneable {

	/**
    * Jeder Knoten kennt seine S�hne (EvaluatorTree)
    */
    private Vector sons;
	/**
    * und seinen Vaterknoten.
    */
    private EvaluatorTree parent;

    private String address = null;

	/**
    * Attribute werden in Vectoren gespeichert, die hier in einem Vector
    * gehalten werden.
    * Die einzelnen enthaltenen Vectoren haben die L�nge 4.
    * 0: Name des Attributes (String)
    * 1: Typ des Attributes (String)
    * 2: Auswertungs-Status des Attributes (String) wenn noch nicht, dann null
    * 3: Wert des Attributes (Object)
    */
	private Vector attributes;

	/**
    * Der Name des Knoten entspricht dem Symbol der Gramatik
    * (Nonterminal bzw. Terminal).
    */
    private String name = "";

	/**
    * Nur da, damit diese Klasse gespeichert und geladen werden kann.
    */
	protected EvaluatorTree() {}

	/**
    * Erzeugt einen neuen Knoten mit dem Symbol name als Namen.
    */
    public EvaluatorTree(String name) {
		sons = new Vector();
		attributes = new Vector();
        this.name = name;
    }

	/**
    * F&uuml;gt ein neues Attribute zu den bestehenden hinzu.
    * @param name Name des Attributes als String
    * @param type Typ des Attributes true = ; false =
    */
	public void addAttribute(String name,boolean type) {
        Vector attribute = new Vector();
        //Name
        attribute.add(name);
        //sythetisiert oder ererbt
        if (type) attribute.add("0");
        else attribute.add("1");
        //bereits evaluiert oder gestartet
        attribute.add(null);
        //Wert des Attributes wird beim Evaluieren gesetzt.
        attribute.add(null);
        for (int i=0; i < attributes.size(); i++) {
            if (((Vector)attributes.elementAt(i)).elementAt(0).equals(name)) {
				attributes.setElementAt(attribute,i);
                return;
            }
        }
		attributes.add(attribute);
    }

	public Object getValueOf(String attributeName) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName))
                return ((Vector)attributes.elementAt(i)).elementAt(3);
        }
        return null;
	}

	public void setValueOf(String attributeName, Object value) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName))
				((Vector)attributes.elementAt(i)).setElementAt(value,3);
        }
	}

	public boolean getTypeOf(String attributeName) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName))
				if (((String)((Vector)
                	attributes.elementAt(i)).elementAt(1)).equals("0"))
                    return true;
            	else return false;
        }
        return true;
	}

	public void setTypeOf(String attributeName, boolean type) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName)) {
				if (type)
                	((Vector)attributes.elementAt(i)).setElementAt("0",1);
                else ((Vector)attributes.elementAt(i)).setElementAt("1",1);
            }
        }
	}

	public void setStateOf(String attributeName, String state) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName))
				((Vector)attributes.elementAt(i)).setElementAt(state,2);
        }
	}

	public String getStateOf(String attributeName) {
        for (int i=0; i < attributes.size(); i++) {
            if (((String)((Vector)attributes.elementAt(i)).elementAt(0)).equals(
                attributeName))
				return (String)((Vector)attributes.elementAt(i)).elementAt(2);
        }
        return null;
	}

    public int getNumberOfSons() {return sons.size();}

    public void addSon(EvaluatorTree subTree) {
        sons.add(subTree);
        subTree.setParent(this);
    }

    public EvaluatorTree getSon(int number) {
        return (EvaluatorTree)sons.elementAt(number);
    }

    public String getName() {return name;}

    public Vector getAttributes() {return attributes;}

    public void setParent(EvaluatorTree tree) {
        this.parent = tree;
    }

    public EvaluatorTree getParent() {return parent;}

    public String getAddress() {
        if (address != null) return address;
        if (getParent() == null) return "0";
        address = getParent().getAddress()+".";
   	    for (int i=0; i < getParent().getNumberOfSons(); i++)
            if (getParent().getSon(i) == this) address = address+i;
		return address;
    }

    public Vector getSons() {return this.sons;}

    public Object getValueOfAttribute(String value) {
        Object retObj = null;
        for (int i=0; i < attributes.size(); i++) {
            if (((Vector)attributes.elementAt(i)).elementAt(0).equals(value))
                retObj = ((Vector)attributes.elementAt(i)).elementAt(3);
        }
        return retObj;
    }

    public Object clone() {
        EvaluatorTree retTree = new EvaluatorTree(getName());
        Vector attrs = retTree.getAttributes();
        for (int i=0; i<attributes.size(); i++)
            attrs.addElement(((Vector)attributes.elementAt(i)).clone());
        for (int i=0; i<sons.size(); i++)
            retTree.addSon((EvaluatorTree)getSon(i).clone());
        return retTree;
    }
}